module baremetal;

version(FreeStanding){}else{
    static assert(0,"not supported not freestanding");
}

//alias Tuple(A...) = A;
import core.attribute;


version(LDC){

    static import ldc.attributes;
    //import ldc.llvmasm;
    //public import ldc.attributes:naked,weak,llvmAttr;

    //enum nounwind = ldc.attributes.llvmAttr("nounwind");
    //enum isr_vector = ldc.attributes.section(".isr_vector");
    enum isr_vector = section(".isr_vector");

}else{
    static assert(0,"not supported yet");
}

//alias VectorFunc = extern(C) void function();
alias VectorFunc = extern(C) void *;

public {
    
}

/**
* 寄存器参数
*/
struct Register
{
	string Access;
	uint oset;
}

/**
* MMIO 内存映射
*/
template MMIO( size_t paddr,T) //if(!isPointer!T)
{
    enum T* MMIO = cast(T*)paddr;
}

/// 不能更名,否则编译会报错
alias  RO_Reg = Register_;
/// 不能更名,否则编译会报错
alias  RW_Reg = Register_;
/// 不能更名,否则编译会报错
alias  WO_Reg = Register_;

/**
* 寄存器类型声明,只保证稳定的存储特性,不包括优化
* 所有额外的优化需要程序员手动完成判定
*/
@optStrategy("optsize")
pragma(inline,true)
struct Register_(alias smask,T = uint)
{
    import core.atomic;
    import std.traits:hasMember;
    import core.bitop:bsf;
    

    private{
        /// 未实现读写权限检查
        template getMethod(string op)
        {
            enum str = typeof(this).stringof;
            static if(str.length < 2){
                enum getMethod = false;
            }else{
                static if(str[0..2] == op){
                    enum getMethod = true;
                }else{
                    enum getMethod = false;
                }                
            }
        }

        /// 读权限
        enum MethodRead = getMethod!("RW") || getMethod!("RO");
        /// 写权限
        enum MethodWrite = getMethod!("RW") || getMethod!("WO");
    }
    
    
    private shared(T) _reg;
    public alias mask = smask;
    pragma(inline,true):
    @disable this();
    static if(MethodRead)
    {
        @property 
        T value() const
        {
            return atomicLoad(_reg);
        }
        alias value this;
    }
    
    /// 直接送出原始状态
    @property 
    ref T orig() => cast(T)_reg;

    /// 获取指针
    @property
    T* ptr() const
    {
        return cast(T*)&_reg;
    }


    // 重载操作符
    /// 赋值重载 
    void opOpAssign(string op)(in T rhs) 
    if(MethodRead && MethodWrite)
    {
        //pragma(msg,"opop:",op);
        atomicOp!(op~"=")(_reg,rhs);
    }
    /// 赋值重载 
    void opAssign()(const T rhs)
    if(MethodWrite)
    {
        atomicStore(_reg,rhs);
    } 
    /// 重载 "=="
    bool opEquals()(const T rhs) const
    if(MethodRead)
    {
        return atomicOp!`==`(_reg,rhs) != 0;
    }

    /***
    * 位域以 property 方式重载  
    * 输出时按位域掩码右侧对齐
    *Params: 
    *   fname = 位域名
    *   rhs = 新位域值,符合掩码
    *Returns: 按位域右侧对齐
    */
    @property
    T opDispatch(string fname)() const
    if(hasMember!(mask, fname) && MethodRead)
    {
        enum smask = __traits(getMember, mask, fname);
        enum spos = bsf(smask);
        
        return (atomicLoad(_reg) & smask) >> spos;
    }
    @property
    void opDispatch(string fname)(in T rhs)
    if(hasMember!(mask, fname) && MethodWrite && MethodRead)
    in( ((rhs << bsf(__traits(getMember, mask, fname)) ) & (~(__traits(getMember, mask, fname))))== 0 )
    {
        enum smask = __traits(getMember, mask, fname);
        enum spos = bsf(smask);
        T oval,nval;
        do{
            oval = atomicLoad(_reg);
            nval = (oval & ~smask) | (rhs << spos);

        }while(!casWeak(&_reg,&oval,nval));
    }
    @property
    void opDispatch(string fname)(in T rhs)
    if(hasMember!(mask, fname) && MethodWrite && !MethodRead)
    in( ((rhs << bsf(__traits(getMember, mask, fname)) ) & (~(__traits(getMember, mask, fname))))== 0 )
    {
        enum smask = __traits(getMember, mask, fname);
        enum spos = bsf(smask);
        atomicStore(_reg,rhs << spos);
    }
    
/*
    import std.traits;

    pragma(msg, __traits(getAttributes, typeof(this)));
    

    pragma(msg,__traits(allMembers, typeof(this)));
    pragma(msg,__traits(identifier, typeof(this)));
    pragma(msg,fullyQualifiedName!(typeof(this)));
*/


    
}
